using System.Diagnostics;
using System.IO;
using Woolpert.Logging;

namespace Woolpert.Compression
{
    /// <summary>
    /// Allows access to external processes and applications through the command line
    /// </summary>
    public static class ExternalApplication
    {
        #region Public Methods

        /// <summary>
        /// Runs an external process on the command line
        /// </summary>
        /// <param name="filePath">Path to the executable</param>
        /// <param name="args">Any arguments you want passed to the executable</param>
        /// <returns>Returns the exit code of the executable</returns>
        public static int RunCommandLine(string filePath, string args)
        {
            return RunCommandLine(filePath, args, true, true);
        }

        /// <summary>
        /// Runs an external process on the command line
        /// </summary>
        /// <param name="filePath">Path to the executable</param>
        /// <param name="args">Any arguments you want passed to the executable</param>
        /// <param name="waitForExit">Whether to wait for external application to complete
        /// before returning</param>
        /// <param name="setWorkingDirectoryToPath">Whether to change the working directory 
        /// of the executable to the executable's directory</param>
        /// <returns>Will return -1 every time if you do not wait for the executable to 
        /// complete. Returns the exit code of the executable</returns>
        public static int RunCommandLine(string filePath, string args, bool waitForExit, bool setWorkingDirectoryToPath)
        {
            var process = new ProcessStartInfo(filePath, string.Format(" {0}", args))
                              {
                                  UseShellExecute = false,
                                  RedirectStandardOutput = false,
                                  CreateNoWindow = true
                              };

            if (setWorkingDirectoryToPath)
            {
                Log.For(typeof (ExternalApplication)).Debug("Setting working directory to the path of the executable.");
                process.WorkingDirectory = Path.GetDirectoryName(filePath);
            }

            Log.For(typeof (ExternalApplication))
                .Info(
                string.Format(
                    "Starting process \"{0}\" with arguments \"{1}\" in working directory \"{2}\". Waiting for exit? {3}",
                    process.FileName,
                    process.Arguments,
                    process.WorkingDirectory,
                    waitForExit
                    ));

            return RunProcess(process, waitForExit);
        }

        #endregion

        #region Private/Protected Methods

        private static int RunProcess(ProcessStartInfo processInfo, bool waitForExit)
        {
            using (var process = new Process())
            {
                int exitCode = -1;

                process.StartInfo = processInfo;

                process.Start();
                if (waitForExit)
                {
                    process.WaitForExit();
                    exitCode = process.ExitCode;
                }

                return exitCode;
            }
        }

        #endregion
    }
}